"""

"""

import abc as abc_module
import keyedset as ks_module
import dictable as d_module

###############################################################################
# Module Exceptions

class ModuleException(Exception): pass
class ModuleError(ModuleException): pass

###############################################################################
# Primary Class

class Collection(ks_module.KeyedSet):
    # centralized lookup?
    # decentralized lookup (subscriber or alternate)?
    # local cache + remote merge?
    # asynchronous updates?
    # 2 way updates (push)?
    # cast init iterable members into __cls__ if not already?

    @abc_module.abstractproperty
    def __cls__(self):
        "The class of which this is a collection."

    @abc_module.abstractmethod
    def search(self, *args, **kwargs):
        "Whatever search parameters the implementer feels appropriate."

    def ordered_by(self, attr):
        "Sort the collection into an ordered one."
        raise NotImplemented()
        # returns OrderedCollection

    def sub(self, attr, val):
        "Pull a subset of the collection."
        coll = self.__class__(primary=self)
        for item in [item for item in self if str(getattr(item, attr)) == value]:
            coll.staticdata.add(item)
        return coll
        
    def generate(self, *args, **kwargs):
        "Create a new instance of the collection's ccontained class (but do not add it)."
        return self.__cls__(*args, **kwargs)


class MutableCollection(Collection, ks_module.MutableKeyedSet):
    def add_by_args(self, *args, **kwargs):
        item = self.generate(*args, **kwargs)
        self.add(item)

    def create(self, *args, **kwargs):
        self.add_by_args(*args, **kwargs)


class InclusiveCollection(Collection):
    def __contains__(self, item):
        return True


class ExclusiveCollection(Collection):
    def __contains__(self, item):
        return False


class OrderedCollection(Collection):
    ""
    def first(self):
        return self[self.keys[0]]
    def last(self):
        return self[self.keys[-1]]
    def __getitem__(self, key):
        if isinstance(key, int):
            key = self.keys()[key]
        return super(OrderedCollection, self).__getitem__(key)


class RelationRow(d_module.Dictable):
    ""

class Relation(Collection):
    ""
    __cls__ = RelationRow

    @abc_module.abstractproperty
    def constraints(self):
        ""
        # like FQ, etc.




